package com.leyou.order.service;

import com.github.wxpay.sdk.WXPayUtil;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.order.config.PayProperties;
import com.leyou.order.dto.CartDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.entity.Order;
import com.leyou.order.entity.OrderDetail;
import com.leyou.order.entity.UserHolder;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.vo.OrderDetailVO;
import com.leyou.order.vo.OrderVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class OrderService {


    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Transactional
    public  Long createOrder(OrderDTO OrderDTO) {

//        1、订单表  tb_order

        //        页面上：
//        `payment_type` tinyint(1) unsigned zerofill NOT NULL COMMENT '支付类型，1、在线支付，2、货到付款',
//                `source_type` int(1) DEFAULT '2' COMMENT '订单来源：1:app端，2：pc端，3：微信端',
//                后台：
//        `order_id` bigint(20) NOT NULL COMMENT '订单id',
//                `total_fee` bigint(20) NOT NULL COMMENT '总金额，单位为分'
//        `actual_fee` bigint(20) NOT NULL COMMENT '实付金额。单位:分。如:20007，表示:200元7分',
//                `user_id` bigint(20) NOT NULL COMMENT '用户id',
//                `status` tinyint(1) DEFAULT NULL COMMENT '订单的状态，1、未付款 2、已付款,未发货 3、已发货,未确认 4、确认收货，交易成功 5、交易取消，订单关闭 6、交易结束，已评价',

        String userId = UserHolder.getUserId();

//        判断用户是否为空
        if(StringUtils.isBlank(userId)){
            throw new LyException(ExceptionEnum.UNAUTHORIZED);
        }

//        通过雪花算法获取id
        long orderId = idWorker.nextId();
        Order order = new Order();
        order.setPaymentType(OrderDTO.getPaymentType());
        order.setSourceType(2);
        order.setOrderId(orderId);
        order.setStatus(OrderStatusEnum.INIT.value());
        order.setUserId(Long.parseLong(userId));
//        总金额：商品的金额
       List<CartDTO> carts = OrderDTO.getCarts();

//       {765:5,522:1} 为了在下面的计算金额时获取数量，在这里放到一个map中
        Map<Long, Integer> skuNumMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
//       获取carts集合中的skuId集合，方便获取集合对象
       List<Long> skuIdList = carts.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
       //通过feign获取集合对象
       List<SkuDTO> skuList = itemClient.findSkusBySkuIds(skuIdList);
       Long total = 0L;
        for (SkuDTO sku : skuList) {
            Long skuId = sku.getId();
            Integer num = skuNumMap.get(skuId);
            total+= sku.getPrice() * num;  //每个商品的单价*数量


          /*  tb_order_detail
            页面上：
            `sku_id` bigint(20) NOT NULL COMMENT 'sku商品id',
                    `num` int(4) NOT NULL COMMENT '购买数量',
                    后台：
            `order_id` bigint(20) NOT NULL COMMENT '订单id',
                    `title` varchar(256) NOT NULL COMMENT '商品标题',
                    `own_spec` varchar(1024) DEFAULT '' COMMENT '商品动态属性键值集',
                    `price` int(16) NOT NULL COMMENT '价格,单位：分',
                    `image` varchar(256) DEFAULT '' COMMENT '商品图片',*/
//        2、订单详情表  tb_order_detail
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(skuId);
            orderDetail.setNum(num);
            orderDetail.setOrderId(order.getOrderId());
            orderDetail.setTitle(sku.getTitle());
            orderDetail.setOwnSpec(sku.getOwnSpec());
            orderDetail.setPrice(sku.getPrice());
            String image = sku.getImages().split(",")[0]; //获取sku中的第一张图片地址
            orderDetail.setImage(image);
            orderDetailMapper.insertSelective(orderDetail);
        }
        order.setTotalFee(total);
        order.setActualFee(total);  //真实付款价格=商品的总金额+运费-优惠
        orderMapper.insertSelective(order);
//        3、物流表 TODO

//        4、减库存 调用itemClient
//        sku中的stock
        itemClient.minusStock(skuNumMap);

        return orderId;
    }

    public OrderVO findById(Long id) {
        Order order = orderMapper.selectByPrimaryKey(id);
        OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);
//        orderVO.setLogistics();  TODO 根据orderId查询物流信息
        OrderDetail od = new OrderDetail();
        od.setOrderId(id);
        List<OrderDetail> detailList = orderDetailMapper.select(od);
        orderVO.setDetailList(BeanHelper.copyWithCollection(detailList, OrderDetailVO.class)); // select  * from tb_order_detail where orderId=?
        return orderVO;
    }

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private PayProperties payProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private String prefix="LY:ORDER:PAY:";

    public String unifiedorder(Long id) {

        String userId = UserHolder.getUserId();
        if(StringUtils.isBlank(userId)){
            throw new LyException(ExceptionEnum.UNAUTHORIZED);
        }
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }

//        先看redis中是否存在
        String code_url = redisTemplate.boundValueOps(prefix + id).get();
        if(StringUtils.isNotBlank(code_url)){
            return code_url;
        }
        String url="https://api.mch.weixin.qq.com/pay/unifiedorder";

        Map<String,String> paramMap = new HashMap<>();
//        公众账号ID	appid	是	String(32)	wxd678efh567hg6787	微信支付分配的公众账号ID（企业号corpid即为此appId）
//        商户号	mch_id	是	String(32)	1230000109	微信支付分配的商户号
//        随机字符串	nonce_str	是	String(32)	5K8264ILTKCH16CQ2502SI8ZNMTM67VS	随机字符串，长度要求在32位以内。推荐随机数生成算法
//        商品描述	body	是	String(128)	腾讯充值中心-QQ会员充值    商品简单描述，该字段请按照规范传递，具体请见参数规定
//        商户订单号	out_trade_no	是	String(32)	20150806125346
//        标价金额	total_fee	是	Int	88 订单总金额，单位为分
//        终端IP	spbill_create_ip	是	String(64)	123.12.12.123
//        通知地址	notify_url	是	String(256)	http://www.weixin.qq.com/wxpay/pay.php
//        交易类型	trade_type	是	NATIVE	JSAPI
//        签名	sign	是	String(32)	C380BEC2BFD727A4B6845133519F3AD6	通过签名算法计算得出的签名值，详见签名生成算法

        paramMap.put("appid",payProperties.getAppID());
        paramMap.put("mch_id",payProperties.getMchID());
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        paramMap.put("body", "乐优商城支付");
        paramMap.put("out_trade_no", id.toString());
        paramMap.put("total_fee", "1");  //TODO 查询订单   order.getActualFee().toString()
        paramMap.put("spbill_create_ip", "127.0.0.1");
        paramMap.put("notify_url", payProperties.getNotifyurl());
        paramMap.put("trade_type","NATIVE");

        try {
            String paramXml = WXPayUtil.generateSignedXml(paramMap, payProperties.getKey());
            String resultXml = restTemplate.postForEntity(url, paramXml, String.class).getBody();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
            code_url = resultMap.get("code_url");
//            放入到redis中
            redisTemplate.boundValueOps(prefix+id).set(code_url,2, TimeUnit.HOURS);
            return code_url;
        } catch (Exception e) {
           throw new LyException(ExceptionEnum.INVALID_PAY_STATUS);
        }
    }

    /**
     * 查询订单支付状态的方法
     * @param id
     * @return
     */
    public Integer queryOrderState(Long id) {
        String userId = UserHolder.getUserId();
        if(StringUtils.isBlank(userId)){
            throw new LyException(ExceptionEnum.UNAUTHORIZED);
        }
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
//
        String url="https://api.mch.weixin.qq.com/pay/orderquery";
        Map<String,String> paramMap = new HashMap();

        paramMap.put("appid",payProperties.getAppID());
        paramMap.put("mch_id",payProperties.getMchID());
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        paramMap.put("out_trade_no", id.toString());
        Map<String, String> resultMap = null;
        try {
            String paramXml = WXPayUtil.generateSignedXml(paramMap, payProperties.getKey());
            String resultXml = restTemplate.postForEntity(url, paramXml, String.class).getBody();
            resultMap = WXPayUtil.xmlToMap(resultXml);

            if(resultMap.get("trade_state").equals("SUCCESS")){
                redisTemplate.delete(prefix+id);
//                修改此订单的状态
                order.setStatus(OrderStatusEnum.PAY_UP.value());
                orderMapper.updateByPrimaryKeySelective(order);
            }
//        1代表未支付，其它是已经支付
            return resultMap.get("trade_state").equals("SUCCESS")?1:0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }

    }
}
